//
//
//
grammar jarl;

options {
    output=AST;
    ASTLabelType=CommonTree;
}

module :   
        (
            member 
            {System.out.println(
             $member.tree==null?"null":$member.tree.toStringTree());}
        )+
	
    ;

member :
        pair SEPARATOR            -> pair
    |   qualifiedName SEPARATOR   -> qualifiedName
    |   namedCollection SEPARATOR -> namedCollection
    ;

	
namedCollection :
       qualifiedName COL_OPEN 
                       namedCollectionStuff
                     COL_CLOSE -> ^(NC qualifiedName namedCollectionStuff)
    ;

namedCollectionStuff : ( (qualifiedName | literal | block) 
                         ( ','^ (qualifiedName | literal | block) )* ) ;
                         
block :
        //BLOCK_OPEN^ (member)+ BLOCK_CLOSE! 
        BLOCK_OPEN (member)+ BLOCK_CLOSE -> ^(BLOCK_OPEN (member)+)
    ;

pair :
        first ':'^ second
    ;

first :         
        qualifiedName
    ; 

second :
        qualifiedName
    |   namedCollection
    |   literal
    ;

literal :   
        INT
    |   FLOAT
    |   STRING
    ;

qualifiedName :
        ID
        ('.'^ ID )*
    ;

BLOCK_OPEN : '{';
BLOCK_CLOSE : '}'; 

COL_OPEN : '(';
COL_CLOSE : ')'; 

NC : ;

ID  :	('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
    ;

INT :	'0'..'9'+
    ;

FLOAT
    :   ('0'..'9')+ '.' ('0'..'9')* EXPONENT?
    |   '.' ('0'..'9')+ EXPONENT?
    |   ('0'..'9')+ EXPONENT
    ;

COMMENT
    :   '//' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;}
    |   '/*' ( options {greedy=false;} : . )* '*/' {$channel=HIDDEN;}
    ;

WS  :   ( ' '
        | '\t'
        | '\r'
        | '\n'
        ) {$channel=HIDDEN;}
    ;

SEPARATOR : ';' ;

STRING
    :  '"' STRING_CHAR* '"'
    ;

fragment
STRING_CHAR : UNICODE_CHAR | ESC_SEQ ;

fragment
UNICODE_CHAR :  ~('\\'|'"') ;

fragment
EXPONENT : ('e'|'E') ('+'|'-')? ('0'..'9')+ ;

fragment
HEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ;

fragment
ESC_SEQ
    :   '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\')
    |   UNICODE_ESC
    |   OCTAL_ESC
    ;

fragment
OCTAL_ESC
    :   '\\' ('0'..'3') ('0'..'7') ('0'..'7')
    |   '\\' ('0'..'7') ('0'..'7')
    |   '\\' ('0'..'7')
    ;

fragment
UNICODE_ESC
    :   '\\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
    ;
